#include "sdbm.h"

#include <iostream>
#include <sstream>
#include <iomanip>
#include <regex>
#include <string>
#include <vector>
#include <ctime>
//#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
//const char * say_what(bool b) { return b ? "true" : "false"; }
using namespace std;
//using namespace boost;
namespace po = boost::program_options;
namespace bf = boost::filesystem;
DBM d;
DBM::db_info di;

void _out(char ch, int num);
void dbinput();
void dboutput();
void dbfind();
void dbfindex();
void dbdel();
void setline();
void setregex();
void dbimp();
void dbext();
void main_loop();

int main(int argc, char *argv[])
{
    clock_t ST, ET;
    string ins,ins2;
    cout << setw(4) << "**" << setw(4) << "**" << "  StrDB数据库控制平台"  << endl;
    cout << setw(4) << "**" << setw(4) << "**" << "  by reghost.lyc @201606" << endl;
    po::options_description desc("可用选项");
    desc.add_options()
                    ("help,h","打印可用选项")
                    ("open,o",po::value<string>(&ins),"打开数据库")
                    ("charset,c",po::value<string>(&ins2),"指定打开文件使用的字符编码");
    po::positional_options_description pod;//位置选项
    pod.add("open,o",1);
    po::variables_map vm;
    try
    {
        po::store(po::command_line_parser(argc, argv).options(desc).positional(pod).run(), vm);
        po::notify(vm);
        if (vm.count("open"))
        {
            if (vm.count("charset"))
            {
                ST = clock();
                if (d.opendb(ins,ins2))
                    ET = clock();
                else
                {
                    cout<<"文件打开错误！ "<<d.GetLastErr() << endl;
                    return 0;
                }
            }
            else
            {
                ST = clock();
                if (d.opendb(ins))
                    ET = clock();
                else
                {
                    cout<<"文件打开错误！ "<<d.GetLastErr() << endl;
                    return 0;
                }
            }
            goto l20;
        }
        else if (vm.count("help"))
        {
            cout << desc << endl;
            cout <<"reghost.lyc@201606"<< setw(50) <<"本数据库有超级牛力"<<endl;
            return 0;
        }
    }
    catch(...)
    {
        cout << "未识别的指令。"<< endl;
        cout << desc << endl;
        cout <<"reghost.lyc@201606"<< setw(50) <<"本数据库有超级牛力"<<endl;
        return 0;
    }
///////////////////////////////////////////////////////
l10:
    int ini;
    cout << "****\n" << setw(4) << "** " << "1：打开  " << setw(4) << "** " << "2：新建  " << setw(4) << "** " << "3：退出" <<endl;
    cin >> ini;
    if (ini ==1)
    {
        cout <<"输入文件名"<<endl;
        cin.get();
        getline(cin,ins);
        cout <<"输入库使用的字符编码，任意单字符自动探测" <<endl;
        cin >> ins2;
        if (ins2.size()>1)
        {
            ST = clock();
            if (d.opendb(ins,ins2))
                ET = clock();
            else
            {
                cout<<"文件打开错误！ "<<d.GetLastErr() << "\n继续？y/n" << endl;
                cin >> ins;
                if (ins =="y" || ins =="Y" )
                    goto l10;
                else
                    return 0;
            }
        }
        else
        {
            ST = clock();
            if (d.opendb(ins))
                ET = clock();
            else
            {
                cout<<"文件打开错误！ "<<d.GetLastErr() << "\n继续？y/n" << endl;
                cin >> ins;
                if (ins =="y" || ins =="Y" )
                    goto l10;
                else
                    return 0;
            }
        }
    }
    else if (ini ==2)
    {
        cout <<"输入文件名"<<endl;
        cin.get();
        getline(cin,ins);
        ST = clock();
        d.newdb(ins);
            ET = clock();
    }
    else
        return 0;
l20:
    di= d.info();
    cout <<"\n**" << setw(4) << " " << " 打开了数据库：" << ins << endl;
    cout <<"**" << setw(4) << " " << " 行*列=总数据量： " << di.row << " * " << di.col << " = " << di.dbsize << endl;
    cout <<"**" << setw(4) << " " << " 最后修改时间： "<< di.ltime << endl;
    cout <<"**" << setw(4) << " " << " 耗时："<<(double)(ET - ST) / CLOCKS_PER_SEC << "秒" << endl;
    main_loop();
}

void main_loop()
{
    string ins;
    int ini;
    do
    {
        cout <<"**" << setw(4) << " " << "1：输入  " << setw(4) << "**" << "2：输出  "<< setw(4) << "**" << "3：查找  " << setw(4) << "**" << "4：查找多列" << endl;
        cout <<"**" << setw(4) << " " << "5：删除  " << setw(4) << "**" << "6：设置换行符"  << setw(4) << "**" << "7：设置正则开关"  << endl;
        cout <<"**" << setw(4) << " " << "8：导入  " << setw(4) << "**" << "9：导出"  << endl;
        cin >> ini;
        switch (ini)
        {
        case 1:
            dbinput();
            break;
        case 2:
            dboutput();
            break;
        case 3:
            dbfind();
            break;
        case 4:
            dbfindex();
            break;
        case 5:
            dbdel();
            break;
        case 6:
            setline();
            break;
        case 7:
            setregex();
            break;
        case 8:
            dbimp();
            break;
        case 9:
            dbext();
            break;
        default:
            cout << "输入错误，";
        }
        cout<< "继续？y/n" <<endl;
        cin >> ins;
    }while (ins =="y" || ins =="Y" );
}

void dbinput()
{
    string sl,sc;
    int i,j;
    char ch;
    clock_t ST,ET;
    vector<string> buf;
    do
    {
        cout << "输入一行，回车结束。输入多行请用换行符" << endl;
        cin.get();
        getline(cin,sl);
        cout << "输入分隔符" <<endl;
        cin >> ch;
        cout << "保存到行，0 保存到新行" << endl;
        cin >> i;
        if ( i >0)
        {
            cout << "0 插入，1 覆盖" << endl;
            cin >> j;
            if (j >0)
                d.write(sl,i, ch);
            else
                d.insert(sl,i, ch);
        }
        else
            d.write(sl,',');
        cout << "已写入，继续？y/n" <<endl;
        cin>> ch;
    }
    while(ch == 'y'||ch == 'Y');
    ST = clock();
    if (d.save())
    {
        ET = clock();
        cout <<"已保存，耗时："<<(double)(ET - ST) / CLOCKS_PER_SEC << "秒" << endl;;
    }
    else
        cout << "保存失败！ " << d.GetLastErr() << endl;
}


void dboutput()
{
    string sl,sc;
    vector<string> buf;
    clock_t ST, ET;
    cout << "输入读取行数，减号读取至行数，0 读取全部行"<< endl;
    cin.get();
    getline(cin,sl);
    const regex re1(R"(\d*)");
    const regex re2(R"(\d*-\d*)");
    ST = clock();
    if(regex_match(sl,re1))
    {
        di= d.info();
        int i = stol(sl);
        if (i >0 )
        {
            ST = clock();
            if (d.read(buf,i))
            {
                ET = clock();
                cout << setw(4)<< i+1<< "|" << right;
                for ( int vi=0 ; vi <buf.size() ; vi++)
                    cout  << setw(7) <<  buf[vi] <<"|" ;
                cout <<left<< endl;
            }
            else
            {
                cout <<"错误！ " << d.GetLastErr();
                return;
            }
        }
        else
        {
            for (i=0 ; i< di.row; i++)
            {
                ST = clock();
                if (d.read(buf, i+1))
                {
                    ET = clock();
                    cout << setw(4)<< i+1<< "|" << right;
                    for ( int vi=0 ; vi <buf.size() ; vi++)
                        cout  << setw(7) <<  buf[vi] <<"|" ;
                    cout <<left<< endl;
                }
                else
                {
                    cout <<"错误！ " <<d.GetLastErr();
                    return;
                }
            }
        }
    }
    else if (regex_match(sl,re2))
    {
        int j = sl.find('-');
        int i = stol(sl.substr(0,j));
        j = stol(sl.substr(j+1));
        di= d.info();
        for (int k=i ; k<= j ; k++)
        {
            ST = clock();
            if (d.read(buf, k))
            {
                ET = clock();
                cout << setw(4)<< k<< "|" << right;
                for ( int vi=0 ; vi <buf.size() ; vi++)
                    cout  << setw(7) <<  buf[vi] <<"|" ;
                cout <<left<< endl;
            }
            else
            {
                cout <<"错误！ " <<d.GetLastErr();
                return;
            }

        }
    }
    cout << "耗时："<<(double)(ET - ST) / CLOCKS_PER_SEC << "秒，";// << endl;
}

void dbfind()
{
    string str;
    int i;
    vector<vector<string>> buf;
    clock_t ST, ET;
    cout << "查找内容（50字符以内）?" << endl;
    cin.get();
    getline(cin,str);
    //cin >> str;
    cout << "指定列（0查找所有）?" << endl;
    cin >> i;
    if (i>0)
    {
        ST = clock();
        if (d.read(i,str,buf))
            ET = clock();
        else
            cout << "找不到匹配，";
    }
    else
    {
        ST = clock();
        if (d.read(str,buf))
            ET = clock();
        else
            cout << "找不到匹配，";
    }
    if (buf.size()>0)
    {
        i=0;
        for (const auto row :buf)
        {
            cout << left << setw(4) << ++i <<"|"<<right;
            for (const auto col :row)
                cout << setw(7)  << col << "|";
            cout <<endl;
        }
        cout << "耗时："<<(double)(ET - ST) / CLOCKS_PER_SEC << "秒，";
    }

}

void dbfindex()
{
    string str;
    char ch;
    int i=0;
    vector<vector<string>> buf;
    clock_t ST, ET;
    cout <<"输入查找条件"<<endl;
    cin.get();
    getline(cin,str);
    cout << "输入分隔符" <<endl;
    //cin.get();
    cin >> ch;
    ST = clock();
    if (d.find(str, ch, buf))
    {
        ET = clock();
        for (auto row:buf)
        {
            cout << left << setw(4) << ++i <<"|"<<right;
            for (const auto col :row)
                cout << setw(7)  << col << "|";
            cout <<endl;
        }
        cout << "耗时："<<(double)(ET - ST) / CLOCKS_PER_SEC << "秒，";
    }
    else
        cout << "找不到匹配，";
}

void dbdel()
{
    int i=0;
    clock_t ST, ET;
    cout << "输入删除列" << endl;
    cin >> i;
    ST = clock();
    if (d.del(i))
    {
        if (d.save())
        {
            ET = clock();
            cout <<"已保存，耗时："<<(double)(ET - ST) / CLOCKS_PER_SEC << "秒，";
        }
        else
            cout <<"保存失败！"<< d.GetLastErr();
    }
    else
        cout << "删除失败！" << d.GetLastErr();
}

void setline()
{
    string str;
    cout <<"输入换行符。注意，换行符应尽量简短。"<<endl;
    cin >> str;
    if (d.setnextline(str))
        cout << "完成 ";
    else
        cout << "错误！" << d.GetLastErr();
}

void setregex()
{
    string sl,sc;
    vector<bool>buf;
    clock_t ST, ET;
    cout << "输入检查序列，每列一个，0关1开，逗号分隔。" << endl;
    cin.get();
    getline(cin,sl);
    istringstream iss(sl);
    while(getline(iss, sc, ','))
    {
        if (sc.size()>0)
        {
            const regex re(R"([\r\n\f])");//匹配回车、换行，换页
            while (regex_search(sc,re))
                sc = sc.substr(0, sc.size()-1);
            buf.push_back(stol(sc));
        }
    }
    ST = clock();
    if(d.setregex(buf))
    {
        ET = clock();
        cout << "完成！耗时："<<(double)(ET - ST) / CLOCKS_PER_SEC << "秒，";// << endl;
    }
    else
        cout << "错误！" << d.GetLastErr();
}

void dbimp()
{
    string str, cod;
    char ch;
    clock_t ST, ET;
    cout << "输入文件名" << endl;
    cin.get();
    getline(cin,str);
    cout <<"输入字段分隔符"<<endl;
    cin >> ch;
    cout <<"输入字符编码，任意单字符自动探测" <<endl;
    cin >> cod;
    if (cod.size()>1)
    {
        ST = clock();
        if (d.importdata(str ,cod ,ch))
        {
            ET = clock();
            cout <<"完成，耗时："<<(double)(ET - ST) / CLOCKS_PER_SEC << "秒，";
        }
        else
            cout << "导入失败！ " << d.GetLastErr();
    }
    else
    {
        ST = clock();
        if (d.importdata(str,ch))
        {
            ET = clock();
            cout <<"完成，耗时："<<(double)(ET - ST) / CLOCKS_PER_SEC << "秒，";
        }
        else
            cout << "导入失败！ " << d.GetLastErr();

    }
}

void dbext()
{
    string str, cod;
    char ch;
    clock_t ST, ET;
    cout << "输入文件名" << endl;
    cin.get();
    getline(cin,str);
    cout <<"输入字段分隔符"<<endl;
    cin >> ch;
    cout <<"输入字符编码，任意单字符使用系统默认" <<endl;
    cin >> cod;
    if (cod.size()>1)
    {
        ST = clock();
        if (d.exportdata(str ,cod ,ch))
        {
            ET = clock();
            cout <<"已保存，耗时："<<(double)(ET - ST) / CLOCKS_PER_SEC << "秒，";// << endl;
        }
        else
            cout << "导出失败！ "<< d.GetLastErr();
    }
    else
    {
        ST = clock();
        if (d.exportdata(str,ch))
        {
            ET = clock();
            cout <<"已保存，耗时："<<(double)(ET - ST) / CLOCKS_PER_SEC << "秒，";// << endl;
        }
        else
            cout << "导出失败！ "<< d.GetLastErr();
    }
}

